问:文件包含 echo file_get_contents($_GET['page']); 和 include($_GET['page']); 在面对 php伪协议时的表现。
非常好的问题!echo file_get_contents($_GET['page']) 和 include($_GET['page']) 在 PHP 中面对伪协议(如 php://filter)时的表现是不同的。我来详细解释一下这两个函数在处理 php://filter 时的行为。
🎯 file_get_contents vs include
1. file_get_contents() 和 php://filter
行为:
file_get_contents() 是一个用于读取文件内容的函数,它会返回文件的原始内容(字符串)。当你将 php://filter 作为文件路径传入时,它会将指定文件的内容通过 php://filter 的过滤器进行处理,然后返回处理后的内容。
针对 php://filter 的表现:
当你通过 file_get_contents() 读取 php://filter 时,会:
- 打开一个文件流
- 应用过滤器(如
convert.base64-encode、convert.iconv.*等) - 返回过滤后的内容
举个例子:
echo file_get_contents('php://filter/read=convert.base64-encode/resource=index.php');
返回结果: 这会返回 index.php 的Base64 编码内容,因为我们指定了 convert.base64-encode 过滤器。
2. include() 和 php://filter
行为:
include() 是用于将指定文件的内容执行到当前脚本中的函数。它会将文件的内容当作 PHP 代码进行执行。如果文件中包含 PHP 代码,它会被执行,如果没有,它会被直接输出。
针对 php://filter 的表现:
当你传入 php://filter 作为路径给 include() 时:
- PHP 会试图将
php://filter作为一个文件进行包含。 - 但是由于
php://filter是伪协议,它的内容并不是实际的 PHP 脚本,因此include()不会执行它。 - 它返回的不是普通的 PHP 代码,而是被过滤后的数据(例如通过
convert.base64-encode编码后的内容)。
所以 include($_GET['page']) 在遇到 php://filter 时并不会执行任何 PHP 代码,它只是将过滤后的内容作为文本包含。
🧩 区别总结:file_get_contents() vs include() 在 php://filter 下的表现
| 特性 | file_get_contents() | include() |
|---|---|---|
| 返回类型 | 返回文件内容,经过过滤器(如 Base64 编码等) | 尝试执行文件内容,若是普通文件则输出内容 |
| PHP 代码执行 | 不执行 PHP 代码,只返回文件内容 | 会执行 PHP 代码(如果文件是 PHP 文件) |
处理 php://filter | 返回过滤后的内容,例如 Base64 编码 | 不执行 PHP 代码,仅返回过滤后的文本 |
| 常用场景 | 用于读取文件内容,尤其是用于文本内容读取 | 用于包括并执行 PHP 文件 |
🔥 在渗透测试中的表现
file_get_contents()可以用于读取php://filter中的过滤内容,比如将一个文件的内容以 Base64 编码返回。include()不会执行php://filter的内容,只会读取并输出经过过滤后的文本。如果你试图用include()去执行 PHP 代码时,它不会像普通文件那样执行。
💡 示例
假设你有以下代码(漏洞存在):
<?php
// 漏洞存在:允许通过 GET 请求包含文件
include($_GET['page']);
?>
攻击者可能构造以下请求来读取文件(但不会执行 PHP 代码):
/vuln.php?page=php://filter/read=convert.base64-encode/resource=secret.php
这将返回 secret.php 文件的 Base64 编码内容,但不会执行其中的 PHP 代码。
而如果你使用 file_get_contents:
echo file_get_contents('php://filter/read=convert.base64-encode/resource=secret.php');
同样会返回该文件的 Base64 编码,而不会执行其中的 PHP 代码。
但如果你想执行 PHP 代码:
/vuln.php?page=secret.php
通过这种方式,你能够执行 secret.php 文件中的 PHP 代码。
🛡️ 防御建议
- 不要让用户控制
include()和require()的路径,这可以防止文件包含漏洞。 - 使用
filter_input()和filter_var()对用户输入进行有效验证和过滤。 - 使用
open_basedir限制可访问的文件路径。 - 确保
allow_url_include设为Off,禁用远程文件包含。